home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / CShell⁄THINK C / File.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-20  |  11.6 KB  |  485 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:         CShell
  5. ** File:            file.c
  6. ** Some code from:  Traffic Light 2.0 version, by Keith Rollin & John Harvey
  7. ** Modified by:     Eric Soldan
  8. **
  9. ** Copyright © 1990-1991 Apple Computer, Inc.
  10. ** All rights reserved.
  11. */
  12.  
  13.  
  14.  
  15. /*****************************************************************************/
  16.  
  17.  
  18.  
  19. #include "CShell.h"                /* Get the CShell includes/typedefs, etc.    */
  20. #include "CShellCommon.h"        /* Get the stuff in common with rez.        */
  21. #include "CShell.protos"        /* Get the prototypes for CShell.            */
  22.  
  23. #ifndef __ERRORS__
  24. #include <Errors.h>
  25. #endif
  26.  
  27. #ifndef __PACKAGES__
  28. #include <Packages.h>
  29. #endif
  30.  
  31. #ifndef __TOOLUTILS__
  32. #include <ToolUtils.h>
  33. #endif
  34.  
  35. #ifndef __UTILITIES__
  36. #include "Utilities.h"
  37. #endif
  38.  
  39.  
  40.  
  41. /*****************************************************************************/
  42.  
  43.  
  44.  
  45. static Boolean    gIncNewFileNumFlag = true;
  46.  
  47.  
  48.  
  49. /*****************************************************************************/
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. /* This function disposes of the document.  It checks to see if a file is
  55. ** currently open for the document.  If it is, then the document is closed.
  56. ** Once there is no open file for the document, the memory occupied by the
  57. ** document is released.
  58. */
  59.  
  60. #pragma segment File
  61. OSErr    AppDisposeDocument(FileRecHndl frHndl)
  62. {
  63.     OSErr        err;
  64.  
  65.     err = noErr;
  66.  
  67.     if (frHndl) {
  68.         if ((*frHndl)->fileState.fss.vRefNum != kInvalVRefNum)
  69.             err = FSClose((*frHndl)->fileState.refNum);
  70.                 /* Close the file, if opened. */
  71.  
  72.         AppFreeDocument(frHndl);
  73.             /* Free all application-specific ram for the document. */
  74.  
  75.         DisposHandle((Handle)frHndl);
  76.             /* Release memory for the document handle. */
  77.     }
  78.  
  79.     return(err);
  80. }
  81.  
  82.  
  83.  
  84. /*****************************************************************************/
  85.  
  86.  
  87.  
  88. /* This function returns whether or not the document is dirty.
  89. */
  90.  
  91. #pragma segment File
  92. Boolean    AppDocumentDirty(FileRecHndl frHndl)
  93. {
  94.     return((*frHndl)->fileState.docDirty);
  95. }
  96.  
  97.  
  98.  
  99. /*****************************************************************************/
  100.  
  101.  
  102.  
  103. /* This function creates a new document.  A handle is created as the
  104. ** reference to the document.  Header information is placed in this handle.
  105. ** The application-specific data follows this header information.  The
  106. ** handle is returned (or nil upon failure), and typically the handle is
  107. ** then stored in the refCon field of the window.  Note that this is a
  108. ** convention, and is not mandatory.  This allows a document to exist that
  109. ** has no window.  A document with no window is useful when the application
  110. ** is called from the finder in response to a print request.  The document
  111. ** can be loaded and printed without involving a window on the screen.
  112. */
  113.  
  114.  
  115. #pragma segment File
  116. OSErr    AppNewDocument(FileRecHndl *returnHndl)
  117. {
  118.     static short    untitledCount;
  119.     FileRecHndl        frHndl;
  120.     FileRecPtr        frPtr;
  121.     Str255            untitled;
  122.     char            *pstr;
  123.     OSErr            err;
  124.  
  125.     err = memFullErr;
  126.     if (*returnHndl = frHndl = (FileRecHndl)NewHandle(sizeof(FileRec))) {
  127.         GetIndString(untitled, rMiscStrings, sOrigName);
  128.         frPtr = *frHndl;
  129.         frPtr->fileState.docDirty    = false;
  130.         frPtr->fileState.readOnly    = false;
  131.         frPtr->fileState.fss.vRefNum = kInvalVRefNum;
  132.         frPtr->fileState.window      = nil;
  133.         pstr = (char *) &(frPtr->fileState.fss.name);
  134.         pstrcpy(pstr, (char *) &untitled);
  135.         if (gIncNewFileNumFlag) ++untitledCount;
  136.         appendi2pstr(pstr, untitledCount);
  137.         if (err = AppInitDocument(frHndl)) {
  138.             DisposHandle((Handle)frHndl);
  139.             *returnHndl = nil;
  140.         }
  141.     }
  142.     return(err);
  143. }
  144.  
  145.  
  146.  
  147. /*****************************************************************************/
  148.  
  149.  
  150.  
  151. #pragma segment File
  152. OSErr    AppOpenDocument(FileRecHndl *result, FSSpecPtr fileToOpen,
  153.                         char permission)
  154. {
  155.     StandardFileReply    reply;
  156.     short                fileRefNum;
  157.     FileRecHndl            frHndl;
  158.     OSErr                err;
  159.     FSSpec                myFileSpec;
  160.     DialogPtr            openDialog;
  161.     short                item;
  162.  
  163.     *result = nil;        /* Assume we will fail. */
  164.  
  165.     if (!fileToOpen) {
  166.         if (DisplayGetFile(&reply))        /* Let the user decide which file. */
  167.             myFileSpec = reply.sfFile;    /* User's choice.                   */
  168.         else
  169.             return(userCanceledErr);    /* User canceled. */
  170.     }
  171.     else
  172.         myFileSpec = *fileToOpen;        /* Pre-designated file to open. */
  173.  
  174.     if (err = AppNewDocument(&frHndl))
  175.         return(err);
  176.             /* We couldn't create an empty document, so give it up. */
  177.  
  178.     err = HOpen(myFileSpec.vRefNum, myFileSpec.parID,
  179.                 myFileSpec.name, permission, &fileRefNum);
  180.  
  181.     if (err == opWrErr) {
  182.  
  183.         ParamText(myFileSpec.name, nil, nil, nil);
  184.         openDialog = GetCenteredDialog(rOpenReadOnly, nil, nil, (WindowPtr)-1L);
  185.         if (!openDialog) {
  186.             AppDisposeDocument(frHndl);
  187.             return(err);
  188.         }
  189.  
  190.         OutlineDialogItem(openDialog, kOpenYes);
  191.         DoSetCursor(&QD(arrow));
  192.         ModalDialog((ModalFilterProcPtr)keyEquivFilter, &item);
  193.         DisposDialog(openDialog);
  194.         if (item != kOpenYes) return(userCanceledErr);
  195.  
  196.         (*frHndl)->fileState.readOnly = true;
  197.         err = HOpen(myFileSpec.vRefNum, myFileSpec.parID,
  198.                     myFileSpec.name, fsRdPerm, &fileRefNum);
  199.     }
  200.  
  201.     if (err) {
  202.         AppDisposeDocument(frHndl);
  203.         return(err);
  204.     }
  205.  
  206.     (*frHndl)->fileState.fss    = myFileSpec;
  207.     (*frHndl)->fileState.refNum = fileRefNum;
  208.  
  209.     if (err = AppReadDocument(frHndl)) {
  210.         AppDisposeDocument(frHndl);
  211.         return(err);
  212.     }
  213.  
  214.     if ((*frHndl)->fileState.readOnly) {
  215.         FSClose((*frHndl)->fileState.refNum);
  216.         (*frHndl)->fileState.fss.vRefNum = kInvalVRefNum;
  217.     }        /* If it's read-only, we don't need the file left open. */
  218.  
  219.     *result = frHndl;
  220.     return(noErr);
  221. }
  222.  
  223.  
  224.  
  225. /*****************************************************************************/
  226.  
  227.  
  228.  
  229. #pragma segment File
  230. OSErr    AppSaveDocument(FileRecHndl    frHndl, WindowPtr window, short saveMode)
  231. {
  232.     Str255                closeOrQuit;
  233.     short                item;
  234.     StandardFileReply    reply;
  235.     OSErr                err;
  236.     short                fileRefNum;
  237.     DialogPtr            saveDialog;
  238.     Boolean                doPrompt;
  239.  
  240. /*    When entering, saveMode is set to the menu command number of the
  241. **    the item that prompted this. Current settings are iSave, iSaveAs,
  242. **    iClose, and iQuit.
  243. */
  244.  
  245.     if (saveMode != iSaveAs) {                        /* If regular save... */
  246.         if (!AppDocumentDirty(frHndl))                /* If file clean...   */
  247.             return(noErr);                            /* Consider it saved. */
  248.     }
  249.  
  250.     pstrcpy((char *) &reply.sfFile.name, (char *) &(*frHndl)->fileState.fss.name);
  251.  
  252.     if ((saveMode == iClose) || (saveMode == iQuit)) {
  253.         /* If implicit save... */
  254.  
  255.         GetIndString(closeOrQuit, rMiscStrings,
  256.                      (saveMode == iClose) ? isClosing : sQuitting);
  257.         ParamText(reply.sfFile.name, closeOrQuit, nil, nil);
  258.  
  259.         saveDialog = GetCenteredDialog(rYesNoCancel, nil, window, (WindowPtr)-1L);
  260.  
  261.         if (saveDialog) {
  262.             OutlineDialogItem(saveDialog, kSaveYes);
  263.             DoSetCursor(&QD(arrow));
  264.             ModalDialog((ModalFilterProcPtr)keyEquivFilter, &item);
  265.             DisposDialog(saveDialog);
  266.         }
  267.         else
  268.             item = kSaveYes;
  269.  
  270.         if (item != kSaveYes) {
  271.             err = noErr;
  272.             if (item == kSaveCanceled) err = userCanceledErr;
  273.             return(err);
  274.         }
  275.     }
  276.  
  277.     doPrompt = (
  278.         (saveMode == iSaveAs) ||
  279.         ((*frHndl)->fileState.fss.vRefNum == kInvalVRefNum)
  280.     );
  281.  
  282.     if (doPrompt) {
  283.         /* Prompt with SFGetFile if doing a Save As or have never saved before. */
  284.  
  285.         if (!DisplayPutFile(&reply))
  286.             return(userCanceledErr);
  287.                 /* User canceled the save. */
  288.  
  289.         if ((*frHndl)->fileState.fss.vRefNum != kInvalVRefNum)
  290.             FSClose((*frHndl)->fileState.refNum);
  291.                 /* Close the old file.  Don't respond to any error here because
  292.                 ** the user may be trying to do a save-as because their old file
  293.                 ** is bad.  If we fail to close the old file, and then respond
  294.                 ** to the error, the user won't get the opportunity to save
  295.                 ** their document to a new file.
  296.                 */
  297.  
  298.         if (err = Create_OpenFile(&reply.sfFile, &fileRefNum)) {
  299.             (*frHndl)->fileState.fss.vRefNum = kInvalVRefNum;
  300.             return(err);
  301.         }
  302.  
  303.         (*frHndl)->fileState.fss    = reply.sfFile;
  304.         (*frHndl)->fileState.refNum = fileRefNum;
  305.             /* This is the new file. */
  306.  
  307.         if (window) AppNewWindowTitle(window);
  308.     }
  309.  
  310.     if (err = AppWriteDocument(frHndl))
  311.         return(err);
  312.  
  313.     (*frHndl)->fileState.docDirty = false;
  314.     (*frHndl)->fileState.readOnly = false;
  315.     return(noErr);
  316. }
  317.  
  318.  
  319.  
  320. /*****************************************************************************/
  321.  
  322.  
  323.  
  324. /* ConvertOldToNewSFReply
  325. **
  326. ** struct StandardFileReply {            struct SFReply {
  327. **     Boolean     sfGood;                <-    Boolean good;
  328. **     Boolean     sfReplacing;        <-    Boolean copy;
  329. **     OSType         sfType;                <-    OSType fType;
  330. **     FSSpec        sfFile;
  331. **                     vRefNum;        <-    real vRefnum from (short vRefNum)
  332. **                     parID;            <-    real dirID from (short vRefNum)
  333. **                     name;            <-    Str63 fName;
  334. **     ScriptCode    sfScript;            <-    iuSystemScript
  335. **     short         sfFlags;            <-    0
  336. **     Boolean     sfIsFolder;            <-    false
  337. **     Boolean     sfIsVolume;            <-    false
  338. **     long        sfReserved1;        <-    0
  339. **     short        sfReserved2;        <-    0
  340. ** };                                    };
  341. */
  342.  
  343. #pragma segment File
  344. void    ConvertOldToNewSFReply(SFReply *oldReply, StandardFileReply *newReply)
  345. {
  346.     OSErr        err;
  347.     long        ignoredProcID;
  348.     
  349.     newReply->sfGood        = oldReply->good;
  350.     newReply->sfReplacing    = oldReply->copy;        /* Correct assignment? */
  351.     newReply->sfType        = oldReply->fType;
  352.  
  353.     err = GetWDInfo(oldReply->vRefNum,
  354.                     &newReply->sfFile.vRefNum,
  355.                     &newReply->sfFile.parID,
  356.                     &ignoredProcID);
  357.     BlockMove((Ptr)&oldReply->fName,
  358.               (Ptr)&newReply->sfFile.name,
  359.               oldReply->fName[0]+1);
  360.  
  361.     /* Punt on the rest. */
  362.     newReply->sfScript        = iuSystemScript;
  363.     newReply->sfFlags        = 0;
  364.     newReply->sfIsFolder    = false;
  365.     newReply->sfIsVolume    = false;
  366.     newReply->sfReserved1    = 0;
  367.     newReply->sfReserved2    = 0;
  368. }
  369.  
  370.  
  371.  
  372. /*****************************************************************************/
  373.  
  374.  
  375.  
  376. /* Create_OpenFile
  377. **
  378. ** Opens the file specified by the passed FSSpec, creating it if it doesn't
  379. ** already exist. Refturns the refnum of the open file to the application.
  380. ** File Manager errors are reported and returned.
  381. */
  382.  
  383. #pragma segment File
  384. OSErr    Create_OpenFile(FSSpec *file, short *refNum)
  385. {
  386.     OSErr    err;
  387.  
  388.     err = HCreate(file->vRefNum, file->parID, file->name, docCreator, docFileType);
  389.     if (err == dupFNErr) {
  390.  
  391.         /* The user already told Standard File to replace the old file
  392.            so let's get rid of it. */
  393.  
  394.         HDelete(file->vRefNum, file->parID, file->name);
  395.  
  396.         /* Try creating it again. */
  397.         err = HCreate(file->vRefNum, file->parID, file->name, docCreator, docFileType);
  398.     }
  399.  
  400.     if (!err) {
  401.         err = HOpen(file->vRefNum, file->parID, file->name, fsRdWrPerm, refNum);
  402.         if (err)
  403.             HDelete(file->vRefNum, file->parID, file->name);
  404.     }
  405.  
  406.     return(err);
  407. }
  408.  
  409.  
  410.  
  411. /*****************************************************************************/
  412.  
  413.  
  414.  
  415. /* DisplayGetFile
  416. **
  417. ** Simple routine to display a list of files with our file type.
  418. */
  419.  
  420. #pragma segment File
  421. Boolean DisplayGetFile(StandardFileReply *reply)
  422. {
  423.     SFTypeList    typeList = {docFileType};
  424.     Point        where = {100, 100};
  425.     SFReply        oldReply;
  426.  
  427.     if (gSystemVersion >= 0x0700)    /* If new standard file available... */
  428.         StandardGetFile(nil, 1, typeList, reply);
  429.  
  430.     else {
  431.         SFGetFile(where, (ConstStr255Param) "\pSelect a document to open.",
  432.                          nil, 1, typeList, nil, &oldReply);
  433.  
  434.         ConvertOldToNewSFReply(&oldReply, reply);
  435.     }
  436.  
  437.     return(reply->sfGood);
  438. }
  439.  
  440.  
  441.  
  442. /*****************************************************************************/
  443.  
  444.  
  445.  
  446. /* DisplayPutFile
  447. **
  448. ** Displays the StandardFile PutFile dialog box. Fills out the passed reply
  449. ** record, and returns the sfGood field as a result.
  450. */
  451.  
  452. #pragma segment File
  453. Boolean DisplayPutFile(StandardFileReply *reply)
  454. {
  455.     Str255        prompt;
  456.     Point        where = {100, 100};
  457.     SFReply        oldReply;
  458.  
  459.     GetIndString(prompt, rMiscStrings, sSFprompt);
  460.  
  461.     if (gSystemVersion >= 0x0700)    /* If new standard file available... */
  462.         StandardPutFile(prompt, reply->sfFile.name, reply);
  463.     else {
  464.         SFPutFile(where, prompt, reply->sfFile.name, nil, &oldReply);
  465.         ConvertOldToNewSFReply(&oldReply, reply);
  466.     }
  467.  
  468.     return(reply->sfGood);
  469. }
  470.  
  471.  
  472.  
  473. /*****************************************************************************/
  474.  
  475.  
  476.  
  477. #pragma segment File
  478. void    IncNewFileNum(Boolean flag)
  479. {
  480.     gIncNewFileNumFlag = flag;
  481. }
  482.  
  483.  
  484.  
  485.